package test.concurrent;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 
 * @Description:  [细粒度互斥key锁]   
 * @Author:       [qiushi]   
 * @CreateDate:   [2016年2月22日]   
 * @UpdateUser:   [qiushi]   
 * @UpdateDate:   [2016年2月25日]   
 * @UpdateRemark: [说明本次修改内容]  
 * @Version:      [v1.1]
 */
public class KeyLocks {

	private ConcurrentMap<String, LockRef> locks = new ConcurrentHashMap<String, LockRef>();

	private ReferenceQueue<Object> queue = new ReferenceQueue<Object>();

	private KeyLocks() {
	}

	private static class SingletonHolder {
		static final KeyLocks instance = new KeyLocks();
	}

	public static KeyLocks getInstance() {
		return SingletonHolder.instance;
	}

	public Object getLock(String key) {
		Object lock = locks.get(key).get();
		if (lock == null)
			synchronized (locks) {
				lock = locks.get(key).get();
				if (lock == null) {
					clearCache();
					lock = new byte[0];
					LockRef lockRef = new LockRef(lock, queue, key);
					locks.put(key, lockRef);
				}
			}
		return lock;
	}

	private void clearCache() {
		LockRef ref = null;
		while ((ref = (LockRef) queue.poll()) != null) {
			locks.remove(ref.getKey());
		}
	}

	private class LockRef extends SoftReference<Object> {
		private String key;

		public LockRef(Object ref, ReferenceQueue<Object> q, String key) {
			super(ref, q);
			this.key = key;
		}

		public String getKey() {
			return key;
		}
	}
}